from ..ess import reSlice as _reSlice, typeof
from .base import basePlus

__all__ = [
    "isintPlus",
    "intPlus",
    "isfloatPlus",
    "floatPlus",
]


def uptype(lowtype: type, uptype: type, upclass: type):
    def dec(func):
        def inner(self, other):
            other = uptype(other)
            lowable = other == uptype(lowtype(other))
            res = func(self, other)
            if lowable:
                res = upclass(res)
            return res
        return inner
    return dec


def isintPlus(it) -> bool:
    return isinstance(it, intPlus)


def isfloatPlus(it) -> bool:
    return isinstance(it, floatPlus)


class intPlus(basePlus):
    def __init__(self, value: int = 0):
        """初始化"""
        super().__init__(value)
        self.contain: int = int(self.contain)

    def __len__(self):
        """长度"""
        return len(str(abs(self.contain)))

    def __add__(self, other):
        """加法"""
        return self.same(self.contain+self.subtype()(other))

    def __sub__(self, other):
        """减法"""
        return self+(-other)

    def __mul__(self, other):
        """乘法"""
        return self.same(self.contain*self.subtype()(other))

    def __truediv__(self, other):
        """除法"""
        return self.same(self.contain/self.subtype()(other))

    def __floordiv__(self, other):
        """整除"""
        return self.same(self.contain//self.subtype()(other))

    def __pow__(self, other):
        """次幂"""
        return self.same(self.contain**self.subtype()(other))

    def __mod__(self, other):
        """取模"""
        return self.same(self.contain % self.subtype()(other))

    def __lshift__(self, other):
        """左移"""
        return self.same(self.contain << int(other))

    def __rshift__(self, other):
        """右移"""
        return self.same(self.contain >> int(other))

    def __and__(self, other):
        """按位与"""
        return self.same(self.contain & int(other))

    def __or__(self, other):
        """按位或"""
        return self.same(self.contain | int(other))

    def __xor__(self, other):
        """按位异或"""
        return self.same(self.contain ^ int(other))

    def __invert__(self):
        """按位取反"""
        return self.same(~self.contain)

    def __pos__(self):
        """正号"""
        return getemplus(self, 1)(self)

    def __neg__(self):
        """负号"""
        return getemplus(self, -1)(self)

    def __lt__(self, other):
        """小于号"""
        return self.contain < self.subtype()(other)

    def __eq__(self, other):
        """等于号"""
        return self.contain == self.subtype()(other)

    def __abs__(self):
        """取绝对值"""
        return self.same(abs(self.contain))

    def __round__(self, n):
        """round函数"""
        temp = self.copy()
        for i in range(int(-n)):
            temp -= self[i]*10**i
        return temp

    def __iter__(self):
        """迭代器"""
        for i in range(len(self)):
            yield self[i]

    def __getitem__(self, index):
        """获取某一位上的数"""
        if isinstance(index, (int, intPlus)):
            index = int(index)
            return int(str(self)[-1-index]) if 0 <= index < len(self) else 0
        elif isinstance(index, slice):
            s = _reSlice(index, len(self))
            return [self[i] for i in range(s.start, s.stop, s.step)]
        else:
            raise Exception("Unexpected type.")

    def __setitem__(self, index, value: int):
        """设置某一位上的值"""
        value %= 10
        if isinstance(index, (int, intPlus)):
            index = int(index)
            if index < 0:
                return
            if index < len(self):
                self.contain -= self[index]*10**index
            self.contain += value*10**index
        elif isinstance(index, slice):
            s = _reSlice(index, len(self))
            for i, j in zip(range(s.start, s.stop, s.step), value):
                self[i] = j

    def __delitem__(self, index):
        """删除某一位"""
        if isinstance(index, (int, intPlus)):
            index = int(index)
            if 0 <= index < len(self):
                for i in range(index, len(self)):
                    self[i] = self[i+1]
        elif isinstance(index, slice):
            s = _reSlice(index, len(self))
            for _ in range(s.start, s.stop, s.step):
                del self[s.start if s.step > 0 else s.stop + 1]

    def __reversed__(self):
        """倒转"""
        temp = self.same()
        for i, j in enumerate(self):
            temp[len(self)-1 - i] = j
        return temp*self.sign()

    def sign(self):
        """符号函数"""
        return self//abs(self) if self.contain != 0 else 0

    def plusplus(self, bias: int):
        """自增自减"""
        self.contain += self.subtype()(bias)
        return self


class floatPlus(basePlus):
    def __init__(self, value: float = 0.0):
        """初始化"""
        super().__init__(value)
        self.contain: float = float(self.contain)

    def __len__(self):
        """长度"""
        return len(str(abs(self.contain)))

    def __add__(self, other):
        """加法"""
        return self.same(self.contain+self.subtype()(other))

    def __sub__(self, other):
        """减法"""
        return self+(-other)

    def __mul__(self, other):
        """乘法"""
        return self.same(self.contain*self.subtype()(other))

    def __truediv__(self, other):
        """除法"""
        if float(other) == 0.0:
            return float("inf")
        return self.same(self.contain/self.subtype()(other))

    def __floordiv__(self, other):
        """整除"""
        return self.same(self.contain//self.subtype()(other))

    def __pow__(self, other):
        """次幂"""
        return self.same(self.contain**self.subtype()(other))

    def __mod__(self, other):
        """取模"""
        return self.same(self.contain % self.subtype()(other))

    def __lshift__(self, other):
        """左移"""
        return self.same(self.contain << int(other))

    def __rshift__(self, other):
        """右移"""
        return self.same(self.contain >> int(other))

    def __and__(self, other):
        """按位与"""
        return self.same(self.contain & int(other))

    def __or__(self, other):
        """按位或"""
        return self.same(self.contain | int(other))

    def __xor__(self, other):
        """按位异或"""
        return self.same(self.contain ^ int(other))

    def __invert__(self):
        """按位取反"""
        return self.same(~self.contain)

    def __pos__(self):
        """正号"""
        return getemplus(self, 1)(self)

    def __neg__(self):
        """负号"""
        return getemplus(self, -1)(self)

    def __lt__(self, other):
        """小于号"""
        return self.contain < self.subtype()(other)

    def __eq__(self, other):
        """等于号"""
        return self.contain == self.subtype()(other)

    def __abs__(self):
        """取绝对值"""
        return self.same(abs(self.contain))

    def __round__(self, n):
        """round函数"""
        return self.same()(round(self.contain, n))

    def __iter__(self):
        """迭代器"""
        ...

    def __getitem__(self, index):
        """获取某一位上的数"""
        if isinstance(index, (int, intPlus)):
            index = int(index)
            return int(str(self)[-1-index]) if 0 <= index < len(self) else 0
        elif isinstance(index, slice):
            s = _reSlice(index, len(self))
            return [self[i] for i in range(s.start, s.stop, s.step)]

    def __setitem__(self, index: int, value: int):
        """设置某一位上的值"""
        ...

    def __delitem__(self, index: int):
        """删除某一位"""
        ...

    def __reversed__(self):
        """倒转"""
        ...

    def sign(self):
        """符号函数"""
        return self//abs(self) if self.contain != 0.0 else 0.0

    def plusplus(self, bias: int):
        """自增自减"""
        self.contain += self.subtype()(bias)
        return self

    def lens(self) -> "tuple[int]":
        temp = str(abs(self.contain)).split('.')
        return len(temp[0]), len(temp[1])

    def intplus(self):
        return intPlus(self.contain)


def getemplus(self, bias):
    return type(typeof(self), (self.__class__,), {
        "backward": self,
        "__pos__": lambda self: self.backward.plusplus(bias) if bias > 0 else -self.backward,
        "__neg__": lambda self: self.backward.plusplus(bias) if bias < 0 else -self.backward,
    })


int2float = uptype(int, float, floatPlus)
